package maskedpixel.ogmo 
{
	import flash.geom.Rectangle;
	import flash.utils.*;
	import net.flashpunk.Entity;
	import maskedpixel.ogmo.utils.*;
	import net.flashpunk.FP;
	import net.flashpunk.graphics.Tilemap;
	import net.flashpunk.masks.Grid;
	
	/**
	 * ...
	 * @author Erin M Gunn
	 */
	public class OgmoLevel
	{
		public var x:uint;
		public var y:uint;
		public var width:uint;
		public var height:uint;
		public var settingsObj:Object;
		/**
		 * Stores a list of entities. Generally this is populated by the static loadLevel function.
		 */
		public var entityList:Vector.<Entity>;
		
		/**
		 * Constructor.
		 */
		public function OgmoLevel()
		{
			entityList = new Vector.<Entity>;
		}
		
		/**
		 * Factory function that loads a level with all of the registered items.
		 * @param	level		The embedded OEL file.
		 * @return				A new MpLevel.
		 */
		public static function loadLevel(levelData:ByteArray, settingsContainerClass:Class = null):OgmoLevel
		{
			// get the XML
			var str:String = levelData.readUTFBytes(levelData.length);
			var xml:XML = new XML(str);
			
			if (settingsContainerClass == null)
			{
				settingsContainerClass = OgmoLevelValues;
			}
			
			// define some variables that we will use later on.
			var level:OgmoLevel = new OgmoLevel();
			level.settingsObj = new settingsContainerClass();
			var x:uint;
			var y:uint;
			var e:Entity;
			var clsRef:Class;
			var subXML:XMLList;
			var width:uint = xml.width;
			var height:uint = xml.height;
			
			level.width = width;
			level.height = height;
			
			// -- Load the level values.
			for each(var value:OgmoValue in OgmoProject.ogmoValues)
			{
				if (level.settingsObj.hasOwnProperty(value.name))
				{
					level.settingsObj[value.name] = xml.attribute(value.name);
				}
			}
			
			// -- Load the Layers.
			var grid:Grid;
			var tileSet:OgmoTileSet;
			var tileMap:Tilemap;
			var index:uint;
			var refRect:Rectangle = new Rectangle();
			for each(var layer:OgmoLayer in OgmoProject.ogmoLayers)
			{
				if (layer.type == OgmoLayer.OBJECTS)
				{
					subXML = xml.child(layer.name);
					for each(var obj:OgmoObject in OgmoProject.ogmoObjects)
					{
						clsRef = (getDefinitionByName(obj.cName) as Class);
						for each(var dataElement:XML in subXML.child(obj.name))
						{
							e = (obj.loadFromXML(clsRef, dataElement) as Entity);
							level.entityList.push(e);
						}
					}
					
					for each(var folder:OgmoFolder in OgmoProject.ogmoFolders)
					{
						for each(obj in folder.objectList)
						{
							clsRef = (getDefinitionByName(obj.cName) as Class);
							for each(dataElement in subXML.child(obj.name))
							{
								e = (obj.loadFromXML(clsRef, dataElement) as Entity);
								level.entityList.push(e);
							}
						}
					}
					
					continue;
				}
				
				subXML = xml.child(layer.name);
				clsRef = (getDefinitionByName(layer.cName) as Class);
				e = new clsRef();
				
				if (layer.type == OgmoLayer.TILES && subXML.length() > 0)
				{
					tileSet = OgmoTileSet.tiles[subXML.@set];
					if (tileSet == null)	break;
					tileMap = new Tilemap(FP.getBitmap(tileSet.asset), width, height,
															tileSet.tileWidth,
															tileSet.tileHeight);
					e.graphic = tileMap;
					for each(dataElement in subXML.tile)
					{
						refRect.x = uint(dataElement.@x) / tileSet.tileWidth;
						refRect.y = uint(dataElement.@y) / tileSet.tileHeight;
						index = ((uint(dataElement.@ty) / tileSet.tileHeight) * tileSet.rows) + uint(dataElement.@tx / tileSet.tileWidth);
						tileMap.setTile(refRect.x, refRect.y, index);
					}
					for each(dataElement in subXML.rect)
					{
						refRect.x = uint(dataElement.@x) / tileSet.tileWidth;
						refRect.y = uint(dataElement.@y) / tileSet.tileHeight;
						refRect.width = uint(dataElement.@w) / tileSet.tileWidth;
						refRect.height = uint(dataElement.@h) / tileSet.tileHeight;
						index = ((uint(dataElement.@ty) / tileSet.tileHeight) * tileSet.rows) + uint(dataElement.@tx / tileSet.tileWidth);
						tileMap.setRect(refRect.x, refRect.y, refRect.width, refRect.height, index);
					}
					if (e.type == null)	e.type = "tileMap";
					level.entityList.push(e);
					continue;
				}
				
				if (layer.type == OgmoLayer.GRID && subXML.length() > 0)
				{
					grid = new Grid(width, height, layer.gridSize, layer.gridSize);
					grid.usePositions = true;
					e.mask = grid;
					for each(dataElement in subXML.rect)
					{
						grid.setRect(dataElement.@x, dataElement.@y, dataElement.@w, dataElement.@h);
					}
					
					if (e.type == null) e.type = "grid";
					level.entityList.push(e);
				}
				
			}
			
			return level;
		}
	}
}